import { forwardRef, ReactNode, Ref } from 'react'
import { useCreation, useMemoizedFn } from 'ahooks'
import _ from 'lodash'
import classNames from 'classnames'
import { ClientSideRowModelModule } from '@ag-grid-community/client-side-row-model'
import { ModuleRegistry } from '@ag-grid-community/core'
import { AG_GRID_LOCALE_CN } from '@ag-grid-community/locale'
import { AgGridReact, AgGridReactProps } from '@ag-grid-community/react'
import { ClipboardModule } from '@ag-grid-enterprise/clipboard'
import { ColumnsToolPanelModule } from '@ag-grid-enterprise/column-tool-panel'
import { MenuModule } from '@ag-grid-enterprise/menu'
import { RangeSelectionModule } from '@ag-grid-enterprise/range-selection'
import { StatusBarModule } from '@ag-grid-enterprise/status-bar'

import { LoadingOverlayComponent, NoRowsOverlayComponent } from './components/components'
import { DateCellEditor } from './components/DateCellEditor'
import { DateCellRenderer } from './components/DateCellRenderer'
import { InputCellEditor } from './components/InputCellEditor'
import { InputCellRenderer } from './components/InputCellRenderer'
import { InputNumberCellEditor } from './components/InputNumberCellEditor'
import { InputNumberCellRenderer } from './components/InputNumberCellRenderer'
import { RadioGroupCellEditor } from './components/RadioGroupCellEditor'
import { RadioGroupCellRenderer } from './components/RadioGroupCellRenderer'
import { SelectCellEditor } from './components/SelectCellEditor'
import { SelectCellRenderer } from './components/SelectCellRenderer'
import { theme } from './theme'
import styles from './styles.module.less'

ModuleRegistry.registerModules([
  // 行基本功能
  ClientSideRowModelModule,
  // 范围选择功能，付费版
  RangeSelectionModule,
  // 剪贴板功能，付费版
  ClipboardModule,
  // 列工具面板功能，付费版
  ColumnsToolPanelModule,
  // 菜单功能，付费版
  MenuModule,
  // 状态栏功能，付费版
  StatusBarModule,
])

/** CusAgGrid 组件 props */
interface ICusAgGridProps<TData = any> extends Omit<AgGridReactProps<TData>, 'localeText' | 'loadThemeGoogleFonts'> {
  /** @default CusAgGrid.defaultTheme */
  theme?: AgGridReactProps<TData>['theme']
  /** @default 41 */
  headerHeight?: AgGridReactProps<TData>['headerHeight']
  /** @default true */
  cellSelection?: AgGridReactProps<TData>['cellSelection']
  /** @default true */
  suppressCutToClipboard?: AgGridReactProps<TData>['suppressCutToClipboard']
  /** @default false */
  suppressMenuHide?: AgGridReactProps<TData>['suppressMenuHide']
  /** @default true */
  suppressCsvExport?: AgGridReactProps<TData>['suppressCsvExport']
  /** @default true */
  suppressExcelExport?: AgGridReactProps<TData>['suppressExcelExport']
  /** @default '根据行对象自动生成' */
  getRowId?: AgGridReactProps<TData>['getRowId']
}

/** AgGridReact 组件封装 */
const CusAgGrid: (<TData = any>(props: ICusAgGridProps<TData> & { ref?: Ref<AgGridReact<TData>> }) => ReactNode) & {
  /** CusAgGrid 组件默认主题 */
  defaultTheme: typeof theme
  /** 单元格日期编辑组件 */
  DateCellEditor: typeof DateCellEditor
  /** 单元格选择编辑组件 */
  SelectCellEditor: typeof SelectCellEditor
  /** 单元格单选组编辑组件 */
  RadioGroupCellEditor: typeof RadioGroupCellEditor
  /** 单选组渲染组件（始终编辑态） */
  RadioGroupCellRenderer: typeof RadioGroupCellRenderer
  /** 数值编辑组件 */
  InputNumberCellEditor: typeof InputNumberCellEditor
  /** 数值渲染组件（始终编辑态） */
  InputNumberCellRenderer: typeof InputNumberCellRenderer
  /** 输入编辑组件 */
  InputCellEditor: typeof InputCellEditor
  /** 输入渲染组件（始终编辑态） */
  InputCellRenderer: typeof InputCellRenderer
  /** 选择渲染组件（始终编辑态） */
  SelectCellRenderer: typeof SelectCellRenderer
  /** 日期渲染组件（始终编辑态） */
  DateCellRenderer: typeof DateCellRenderer
} = Object.assign(
  forwardRef<AgGridReact, ICusAgGridProps>(function WrapperAgGridReact(props, ref) {
    const { className, getContextMenuItems } = props

    const rowIdCache = useCreation(() => new WeakMap(), [])
    const getRowId = useMemoizedFn<NonNullable<ICusAgGridProps['getRowId']>>(({ data }) => {
      if (!rowIdCache.has(data)) rowIdCache.set(data, _.uniqueId())
      return rowIdCache.get(data) // 解决不渲染问题
    })

    const mergedGetContextMenuItems = useMemoizedFn<NonNullable<ICusAgGridProps['getContextMenuItems']>>(e => {
      let list = getContextMenuItems?.(e) || e.defaultItems || []
      if (list[list.length - 1] === 'separator') list = list.slice(0, -1) // 移除最后一项分隔线
      return list
    })

    return (
      <AgGridReact
        theme={CusAgGrid.defaultTheme}
        headerHeight={41}
        cellSelection
        suppressCutToClipboard
        suppressMenuHide={false}
        suppressCsvExport
        suppressExcelExport
        loadingOverlayComponent={LoadingOverlayComponent}
        noRowsOverlayComponent={NoRowsOverlayComponent}
        getRowId={getRowId}
        {...props}
        getContextMenuItems={mergedGetContextMenuItems}
        className={classNames(styles.CusAgGrid, className)}
        localeText={AG_GRID_LOCALE_CN}
        loadThemeGoogleFonts={false}
        ref={ref}
      />
    )
  }),

  {
    defaultTheme: theme,
    DateCellEditor,
    SelectCellEditor,
    RadioGroupCellEditor,
    RadioGroupCellRenderer,
    InputNumberCellEditor,
    InputNumberCellRenderer,
    InputCellEditor,
    InputCellRenderer,
    SelectCellRenderer,
    DateCellRenderer,
  },
)

export type { AgGridReact, ICusAgGridProps }
export { CusAgGrid }
